package chagine.core.config.api;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 版本控制
 */
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {

    private static final Pattern VERSION_PATTERN = Pattern.compile("^[0-9]+\\.[0-9]+\\.[0-9]+$");
    //api版本号
    private String apiVersion;
    private static final String HEAD_PARAMS_VERSION = "x-api-version";
    private static final String GET_PARAMS_VERSION = "x-api-version";

    public ApiVersionCondition(String apiVersion) {
        this.apiVersion = apiVersion;
    }

    /**
     * 将不同的筛选条件进行合并
     */
    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        // 采用最后定义优先原则，则方法上的定义覆盖类上面的定义
        return new ApiVersionCondition(other.getApiVersion());
    }

    /**
     * 版本比对，用于排序
     */
    @Override
    public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
        //优先匹配最新版本号
        return compareTo(other.getApiVersion(), this.apiVersion);
    }

    /**
     * 根据request的请求版本号进行查找匹配的筛选条件
     */
    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
        String method = request.getMethod();
        String version = request.getHeader(HEAD_PARAMS_VERSION);
        if (StringUtils.isBlank(version)) {
            if ("get".equalsIgnoreCase(method)) {
                version = request.getParameter(GET_PARAMS_VERSION);
            }
        }
        if (StringUtils.isNotBlank(version)) {
            Matcher matcher = VERSION_PATTERN.matcher(version);
            if (matcher.find()) {
                if (compareTo(version, this.apiVersion) >= 0) {
                    return this;
                }
            }
        }
        if (this.apiVersion.equals("0.0.0")) {
            return this;
        }
        return null;
    }

    private static int compareTo(String version1, String version2) {
        String[] split1 = version1.split("\\.");
        String[] split2 = version2.split("\\.");
        for (int i = 0; i < split1.length; i++) {
            int n1 = Integer.parseInt(split1[i]);
            int n2 = Integer.parseInt(split2[i]);
            if (n1 < n2) {
                return -1;
            } else if (n1 > n2) {
                return 1;
            }
        }
        return 0;
    }

    public String getApiVersion() {
        return apiVersion;
    }
}